# -*- coding: utf-8 -*-
from __future__ import print_function

from decimal import Decimal, getcontext, ROUND_HALF_DOWN
import os

import pandas as pd

from dtrader.barfeed import AbstractTickPriceHandler
from dtrader.event import TickEvent


class HistoricCSVTickPriceHandler(AbstractTickPriceHandler):
    """
    HistoricCSVPriceHandler读取CSV文件里面的tick数据，生成TickEvent
    推送tick事件到事件消息队列中去
    """
    def __init__(self, csv_dir, events_queue, init_tickers=None):
        """
        设置CSV文件目录，事件队列，初始化ticker列表。然后根据ticker列表创建
        每个ticker对应的价格数据序列
        """
        self.csv_dir = csv_dir
        self.events_queue = events_queue
        self.continue_backtest = True
        self.tickers = {}
        self.tickers_data = {}
        if init_tickers is not None:
            for ticker in init_tickers:
                self.subscribe_ticker(ticker)
        self.tick_stream = self._merge_sort_ticker_data()

    def _open_ticker_price_csv(self, ticker):
        """
        根据csv文件目录，打开指定ticker数据的csv文件把数据
        转化成pandas DataFrame
        """
        ticker_path = os.path.join(self.csv_dir, "%s.csv" % ticker)
        self.tickers_data[ticker] = pd.io.parsers.read_csv(
            ticker_path, header=0, parse_dates=True,
            dayfirst=True, index_col=1,
            names=("Ticker", "Time", "Bid", "Ask")
        )

    def _merge_sort_ticker_data(self):
        """
        把所有ticker的数据按时间排序，并集合在一个pandas的dataframe里，这是一种理想
        的情况，用于回测，但用于实盘不行
        """
        return pd.concat(
            self.tickers_data.values()
        ).sort_index().iterrows()

    def subscribe_ticker(self, ticker):
        """
        订阅新的ticker数据
        """
        if ticker not in self.tickers:
            try:
                self._open_ticker_price_csv(ticker)
                dft = self.tickers_data[ticker]
                row0 = dft.iloc[0]
                ticker_prices = {
                    "bid": Decimal(str(row0["Bid"])),
                    "ask": Decimal(str(row0["Ask"])),
                    "timestamp": dft.index[0]
                }
                self.tickers[ticker] = ticker_prices
            except OSError:
                print(
                    "Could not subscribe ticker %s "
                    "as no data CSV found for pricing." % ticker
                )
        else:
            print(
                "Could not subscribe ticker %s "
                "as is already subscribed." % ticker
            )

    def get_best_bid_ask(self, ticker):
        """
        获取最优bid，ask价格
        """
        if ticker in self.tickers:
            bid = self.tickers[ticker]["bid"]
            ask = self.tickers[ticker]["ask"]
            return bid, ask
        else:
            print(
                "Bid/ask values for ticker %s are not "
                "available from the PriceHandler." % ticker
            )
            return None, None

    def get_last_timestamp(self, ticker):
        """
        返回指定ticker的最近时间戳
        """
        if ticker in self.tickers:
            timestamp = self.tickers[ticker]["timestamp"]
            return timestamp
        else:
            print(
                "Timestamp for ticker %s is not "
                "available from the %s." % (ticker, self.__class__.__name__)
            )
            return None

    def stream_next(self):
        """
        推送TickEvent到事件消息队列
        """
        try:
            index, row = next(self.tick_stream)
        except StopIteration:
            self.continue_backtest = False
            return

        getcontext().rounding = ROUND_HALF_DOWN
        ticker = row["Ticker"]
        bid = Decimal(str(row["Bid"])).quantize(
            Decimal("0.00001")
        )
        ask = Decimal(str(row["Ask"])).quantize(
            Decimal("0.00001")
        )

        self.tickers[ticker]["bid"] = bid
        self.tickers[ticker]["ask"] = ask
        self.tickers[ticker]["timestamp"] = index

        # 创建TickEvent，推送到事件消息队列
        tev = TickEvent(ticker, index, bid, ask)
        self.events_queue.put(tev)
